/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ua.yandex.collections;

/**
 *
 * @author Mariya
 */
public class MyArrayList implements MyList {

    private static final int STARTSIZE = 10;
    private Object[] array;
    private int size;

    public MyArrayList() {
        array = new Object[STARTSIZE];
        size = 0;
    }

    public MyArrayList(int capacity) {
        if (capacity < 0) {
            throw new IndexOutOfBoundsException();
        }
        array = new Object[capacity];
        size = 0;
    }

    public MyArrayList(Object[] c) {
        array = c.clone();
        size = c.length;
    }

    @Override
    public void add(Object e) {
        if (array.length == size) {
            Object[] newArray = new Object[(size * 3) / 2 + 1];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
        array[size] = e;
        size++;
    }

    private void checkForExceptions(int index, boolean chekingEqual) {
        if (index > size || index < 0) {
            throw new IndexOutOfBoundsException();
        }
        if (chekingEqual && index == size) {
            throw new IndexOutOfBoundsException();
        }
    }

    @Override
    public void add(int index, Object e) {
        checkForExceptions(index, false);
        if (array.length == size) {
            Object[] newArray = new Object[(size * 3) / 2 + 1];
            System.arraycopy(array, 0, newArray, 0, index);
            newArray[index] = e;
            System.arraycopy(array, index, newArray, index + 1, size - index);
            array = newArray;
        } else {
            System.arraycopy(array, index, array, index + 1, size - index);
            array[index] = e;
        }
        size++;
    }

    @Override
    public void addAll(Object[] c) {
        if (array.length - size < c.length) {
            Object[] newArray = new Object[array.length + c.length];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
        System.arraycopy(c, 0, array, size, c.length);
        size += c.length;
    }

    @Override
    public void addAll(int index, Object[] c) {
        checkForExceptions(index, false);
        if (array.length - size < c.length) {
            Object[] newArray = new Object[array.length + c.length];
            System.arraycopy(array, 0, newArray, 0, index);
            System.arraycopy(c, 0, newArray, index, c.length);
            System.arraycopy(array, index, newArray, index + c.length, size - index);
            array = newArray;
        } else {
            System.arraycopy(array, index, array, index + c.length, size - index);
            System.arraycopy(c, 0, array, index, c.length);
        }
        size += c.length;
    }

    @Override
    public Object get(int index) {
        checkForExceptions(index, true);
        return array[index];
    }

    @Override
    public Object remove(int index) {
        checkForExceptions(index, true);
        Object removed = array[index];
        if ((size * 3) / 2 < array.length) {
            Object[] newArray = new Object[((size - 1) * 3) / 2 + 1];
            System.arraycopy(array, 0, newArray, 0, index);
            System.arraycopy(array, index + 1, newArray, index, size - index - 1);
            array = newArray;
        } else {
            System.arraycopy(array, index + 1, array, index, size - index - 1);
        }
        size--;
        return removed;
    }

    @Override
    public void set(int index, Object e) {
        checkForExceptions(index, true);
        array[index] = e;
    }

    @Override
    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            while (index < size && array[index] != null) {
                index++;
            }
        } else {
            while (index < size && !array[index].equals(o)) {
                index++;
            }
        }
        if (index == size) {
            index = -1;
        }
        return index;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        array = new Object[STARTSIZE];
        size = 0;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public Object[] toArray() {
        Object[] result = new Object[size];
        System.arraycopy(array, 0, result, 0, size);
        return result;
    }

    @Override
    public String toString() {
        if (size == 0) {
            return "";
        }
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < size - 1; ++i) {
            buf.append(array[i]);
            buf.append(",");
        }
        buf.append(array[size - 1]);
        return buf.toString();
    }

    public void ensureCapacity(int minCapacity) {
        if (array.length < minCapacity) {
            Object[] newArray = new Object[minCapacity];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
    }
}
